using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using OSGeo.MapServer;
using System.Drawing;
using System.IO;
using System.Data;
using Pgmobile.Models.Mapa;
using System.Text;
using ServiciosGeograficos.Persistencia;
using Pgmobile.Reconocimiento;
using ServiciosGeograficos.Reconocimiento;


namespace Pgmobile.Controllers
{
    public class MapaController : Controller
    {
        //
        // GET: /Mapa/

        public ActionResult Mapa()
        {
            if (Request.IsAuthenticated)
            {

                // Cargo los metodos de consulta
                List<SelectListItem> lsMetodos = new List<SelectListItem>();
                SelectListItem selectItemDireccion = new SelectListItem();
                selectItemDireccion.Value = "divDireccionCalle";
                selectItemDireccion.Text = "Busqueda por interseccion de calles";
                selectItemDireccion.Selected = true;
                SelectListItem selectItemPuerta = new SelectListItem();
                selectItemPuerta.Value = "divDireccionPuerta";
                selectItemPuerta.Text = "Busqueda por numero de puerta";
                selectItemPuerta.Selected = false;
                SelectListItem selectItemRecorridos = new SelectListItem();
                selectItemRecorridos.Value = "divRecorridos";
                selectItemRecorridos.Text = "Mostrar recorrido";
                selectItemRecorridos.Selected = false;

                lsMetodos.Add(selectItemDireccion);
                lsMetodos.Add(selectItemPuerta);
                lsMetodos.Add(selectItemRecorridos);

                // Cargo las lineas de omnibus
                List<SelectListItem> lsLineasOmnibus = new List<SelectListItem>();

                PostgresDAO daoPostgres = new PostgresDAO();
                // TODO Investigar por que en posicion_omnibus hay menos omnibus que en lineas

                String query = "select gid,nombre from lineas where gid <= 255 order by nombre";
                DataSet dataSet = daoPostgres.ejecutarQuery(query, "lineas");
                foreach (DataRow row in dataSet.Tables["lineas"].Rows)
                {
                    SelectListItem selectItemRecorrido = new SelectListItem();
                    selectItemRecorrido.Value = "" + (int)row["gid"];
                    selectItemRecorrido.Text = (String)row["nombre"];
                    selectItemRecorrido.Selected = false;
                    lsLineasOmnibus.Add(selectItemRecorrido);
                }


                ViewData["lineasOmnibus"] = lsLineasOmnibus;
                ViewData["metodoBusqueda"] = lsMetodos;

            }
            return View();
        }

        public JsonResult ObtenerPuntosLinea(String linea, int idParadaOrigen, int idParadaDestino)
        {
            DateTime calculationStart = DateTime.Now;
            JsonRespuestaLineas respuesta = new JsonRespuestaLineas();
            Pgmobile.calcularDemora.ServicioCalculoDatos servicioCalculoDemora = new Pgmobile.calcularDemora.ServicioCalculoDatos();
            Pgmobile.devolverInformacionLinea.Service servicioLineas = new Pgmobile.devolverInformacionLinea.Service();
            Pgmobile.calcularDemora.DatosDemora[] datosDemoraOrigen = null;
            Pgmobile.calcularDemora.DatosDemora[] datosDemoraDestino = null;
            if (idParadaOrigen != 0 && idParadaDestino != 0)
            {
                DataSet dsSublineasParadasOrigen = servicioLineas.devolverSubLineasParada((short)idParadaOrigen, int.Parse(linea));
                DataSet dsSublineasParadasDestino = servicioLineas.devolverSubLineasParada((short)idParadaDestino, int.Parse(linea));
                int[] idSublineasParadasOrigen = new int[dsSublineasParadasOrigen.Tables["Table"].Rows.Count];
                int[] idSublineasParadasDestino = new int[dsSublineasParadasDestino.Tables["Table"].Rows.Count];
                int cont = 0;
                foreach (DataRow row in dsSublineasParadasOrigen.Tables["Table"].Rows)
                {
                    idSublineasParadasOrigen[cont] = (int)row["idSublinea"];
                    cont++;
                }
                cont = 0;
                foreach (DataRow row in dsSublineasParadasDestino.Tables["Table"].Rows)
                {
                    idSublineasParadasDestino[cont] = (int)row["idSublinea"];
                    cont++;
                }

                datosDemoraOrigen = servicioCalculoDemora.CalcularDemoraConOmnibus(linea, idSublineasParadasOrigen, idParadaOrigen);
                datosDemoraDestino = servicioCalculoDemora.CalcularDemoraConOmnibus(linea, idSublineasParadasDestino, idParadaDestino);
            }
            String tab = "\t";
            TextWriter archivoPosicionLinea = new StreamWriter(System.AppDomain.CurrentDomain.BaseDirectory + "posicionesLinea" + Session.SessionID + ".txt");
            archivoPosicionLinea.WriteLine("point" + tab + "title" + tab + "description" + tab + "icon");
            //String rutaIcono = "http://localhost//Pgmobile//Scripts//img//bus5.jpg";
            String rutaIcono = "http://Btk2009:88/Scripts/img/bus5.jpg";
            
            DataTable dataTableLineas = servicioLineas.devolverInformacionLinea(int.Parse(linea));

            if (dataTableLineas.Rows.Count == 0)
            {
                respuesta.estado = false;
            }
            else
            {
                respuesta.estado = true;
                respuesta.sessionId = Session.SessionID;
            }
            int minutosOrigen = -1;
            int minutosDestino = -1;
            for (int i = 0; i < dataTableLineas.Rows.Count && i < 5; i++)
            {
                minutosOrigen = -1;
                minutosDestino = -1;
                DataRow row = dataTableLineas.Rows[i];
                int idOmnibus = (int)row["idOmnibus"];
                String xPosicion = "" + (double)row["x"];
                xPosicion = xPosicion.Replace(',', '.');
                String yPosicion = "" + (double)row["y"];
                yPosicion = yPosicion.Replace(',', '.');
                String textoLinea = "";




                if (idParadaOrigen == 0 && idParadaDestino == 0)
                {
                    archivoPosicionLinea.WriteLine(yPosicion + "," + xPosicion + tab + "El movil se encuentra cerca de:" + tab + "Bulevar Artigas y Rivera" + tab + rutaIcono);
                }
                else
                {


                    minutosOrigen = obtenerTiempoOmnibus(datosDemoraOrigen, idOmnibus);
                    minutosDestino = obtenerTiempoOmnibus(datosDemoraDestino, idOmnibus);

                    if (xPosicion == "468431.65635" && yPosicion == "6137648.50008")
                    {
                        TextWriter archivoPosicionTiempos = new StreamWriter(System.AppDomain.CurrentDomain.BaseDirectory + "posicionesTiempos.txt",true);
                        archivoPosicionTiempos.WriteLine("Llego a pereira y payan a las " + DateTime.Now.ToString());
                        archivoPosicionTiempos.Close();
                    }
                    if (xPosicion == "473348.09386" && yPosicion == "6139253.50008")
                    {
                        TextWriter archivoPosicionTiempos = new StreamWriter(System.AppDomain.CurrentDomain.BaseDirectory + "posicionesTiempos.txt",true);
                        archivoPosicionTiempos.WriteLine("Arranco en la posicion a las " + DateTime.Now.ToString() + " y estima = " + minutosOrigen + " para el id de bondi " + idOmnibus);
                        archivoPosicionTiempos.Close();
                    }


                    DateTime now = DateTime.Now;
                    int calculationMinutes = System.Convert.ToInt32(Math.Round(now.Subtract(calculationStart).TotalMinutes));
                    minutosDestino -= calculationMinutes;
                    minutosOrigen -= calculationMinutes;
                    if (minutosDestino > -1 && minutosOrigen > -1)
                    {
                        textoLinea = yPosicion + "," + xPosicion + tab + "Tiempos estimados: idOmnibus = " + idOmnibus + tab + "Tiempo llegada a la parada origen: " + minutosOrigen + " min";
                        textoLinea += "<br/>Tiempo llegada a la parada destino: " + minutosDestino + " min" + tab + rutaIcono;
                    }
                    else
                    {
                        textoLinea = yPosicion + "," + xPosicion + tab + "Tiempos estimados:  idOmnibus = " + idOmnibus + tab + "El movil ya ha pasado por la parada origen" + tab + rutaIcono;
                    }
                    archivoPosicionLinea.WriteLine(textoLinea);
                }
            }
            archivoPosicionLinea.Close();
            return this.Json(respuesta); ;
        }

        public JsonResult MarcarPunto(String nmCalle, String nmEsquina, String tipo, String numPuerta, String nmCallePuerta, String xOrigen, String yOrigen, String xDestino, String yDestino)
        {
            JsonRespuestaMapa respuesta = new JsonRespuestaMapa();

            if (Request.IsAuthenticated)
            {
                Interprete interprete = new Interprete();
                DataSet dataSet;
                DataTable dtParada;
                DataRow rowParada;
                if (tipo.Equals("recorrido"))
                {
                    DataTable table = interprete.darOmnibusPosibles(xOrigen, yOrigen, xDestino, yDestino);
                    respuesta.tipoRequest = "mostrarConsultaRecorrido";
                    bool encontrePosibles = false;
                    int cantBondisPosibles = 0;
                    int idParadaOrigenPosible = 0;
                    int idParadaDestinoPosible = 0;
                    for (int i = 0; i < table.Rows.Count && !encontrePosibles; i++)
                    {
                        DataRow row = table.Rows[i];

                        // Valido que los omnibus posibles obtenidos vayan en el sentido determinado por los puntos
                        // Origen -> Destino
                        int idBondiPosible = (int)row["gid"];
                        dtParada = interprete.darParada(xOrigen, yOrigen, idBondiPosible);
                        if (dtParada.Rows.Count > 0)
                        {
                            rowParada = dtParada.Rows[0];
                            idParadaOrigenPosible = (int)rowParada["id1"];

                            dtParada = interprete.darParada(xDestino, yDestino, idBondiPosible);
                            rowParada = dtParada.Rows[0];
                            idParadaDestinoPosible = (int)rowParada["id1"];
                        }
                        else {
                            idParadaDestinoPosible = 0;
                            idParadaOrigenPosible = 0;
                        }
                        
                        if (idParadaDestinoPosible > idParadaOrigenPosible && cantBondisPosibles == 0)
                        {
                            respuesta.nmOmnibus1 = (String)row["nombre"];
                            respuesta.cdOmnibus1 = (int)row["gid"];
                            respuesta.cantOmnibus = 1;

                            // Obtengo la parada de dicho omnibus

                            dtParada = interprete.darParada(xOrigen, yOrigen, respuesta.cdOmnibus1);
                            rowParada = dtParada.Rows[0];
                            respuesta.idParadaOrigen1 = (int)rowParada["idParada"];
                            respuesta.xParadaOrigen1 = (double)rowParada["xParada"];
                            respuesta.yParadaOrigen1 = (double)rowParada["yParada"];

                            dtParada = interprete.darParada(xDestino, yDestino, respuesta.cdOmnibus1);
                            rowParada = dtParada.Rows[0];
                            respuesta.idParadaDestino1 = (int)rowParada["idParada"];
                            respuesta.xParadaDestino1 = (double)rowParada["xParada"];
                            respuesta.yParadaDestino1 = (double)rowParada["yParada"];
                            cantBondisPosibles++;
                        }
                        else if (idParadaDestinoPosible > idParadaOrigenPosible && cantBondisPosibles == 1)
                        {
                            respuesta.nmOmnibus2 = (String)row["nombre"];
                            respuesta.cdOmnibus2 = (int)row["gid"];
                            respuesta.cantOmnibus = 2;

                            // Obtengo la parada de dicho omnibus

                            dtParada = interprete.darParada(xOrigen, yOrigen, respuesta.cdOmnibus2);
                            rowParada = dtParada.Rows[0];
                            respuesta.idParadaOrigen2 = (int)rowParada["idParada"];
                            respuesta.xParadaOrigen2 = (double)rowParada["xParada"];
                            respuesta.yParadaOrigen2 = (double)rowParada["yParada"];

                            dtParada = interprete.darParada(xDestino, yDestino, respuesta.cdOmnibus2);
                            rowParada = dtParada.Rows[0];
                            respuesta.idParadaDestino2 = (int)rowParada["idParada"];
                            respuesta.xParadaDestino2 = (double)rowParada["xParada"];
                            respuesta.yParadaDestino2 = (double)rowParada["yParada"];
                            cantBondisPosibles++;
                        }
                        else if (idParadaDestinoPosible > idParadaOrigenPosible && cantBondisPosibles == 2)
                        {
                            respuesta.nmOmnibus3 = (String)row["nombre"];
                            respuesta.cdOmnibus3 = (int)row["gid"];
                            respuesta.cantOmnibus = 3;

                            // Obtengo la parada de dicho omnibus

                            dtParada = interprete.darParada(xOrigen, yOrigen, respuesta.cdOmnibus3);
                            rowParada = dtParada.Rows[0];
                            respuesta.idParadaOrigen3 = (int)rowParada["idParada"];
                            respuesta.xParadaOrigen3 = (double)rowParada["xParada"];
                            respuesta.yParadaOrigen3 = (double)rowParada["yParada"];

                            dtParada = interprete.darParada(xDestino, yDestino, respuesta.cdOmnibus3);
                            rowParada = dtParada.Rows[0];
                            respuesta.idParadaDestino3 = (int)rowParada["idParada"];
                            respuesta.xParadaDestino3 = (double)rowParada["xParada"];
                            respuesta.yParadaDestino3 = (double)rowParada["yParada"];
                            encontrePosibles = true;
                        }
                    }
                    if (table.Rows.Count > 0)
                    {
                        respuesta.encontre = true;
                    }
                    respuesta.consultaRecorrido = true;
                    return this.Json(respuesta);
                }
                else
                {
                    

                    if (numPuerta == null || numPuerta.Length == 0)
                    {
                        // Normalizo los nombres de avenidas y calles
                        InterpreteCalles i = new InterpreteCalles();
                        nmCalle = i.normalizaCalles(nmCalle);
                        nmEsquina = i.normalizaCalles(nmEsquina);
                        dataSet = interprete.intersectanCalles(nmCalle, nmEsquina);
                    }
                    else
                    {
                        InterpreteCalles i = new InterpreteCalles();
                        nmCallePuerta = i.normalizaCalles(nmCallePuerta);
                        dataSet = interprete.callePuertas(nmCallePuerta, numPuerta);
                    }

                    // Me fijo si encontre el punto o si existen sugerencias para la calle
                    if (dataSet != null && dataSet.Tables["posiblesEsquinas"] != null && dataSet.Tables["posiblesEsquinas"].Rows.Count > 0)
                    {
                        int cont = 1;
                        respuesta.posiblesEsquinas = true;
                        respuesta.tipoRequest = "mostrarPosiblesCalles";
                        respuesta.cantCalles = dataSet.Tables["posiblesEsquinas"].Rows.Count;
                        foreach (DataRow row in dataSet.Tables["posiblesEsquinas"].Rows)
                        {
                            if (cont == 1)
                            {
                                respuesta.nmEsquinaPosible1 = (String)row["nm_calle"];
                            }
                            else if (cont == 2)
                            {
                                respuesta.nmEsquinaPosible2 = (String)row["nm_calle"];

                            }
                            else if (cont == 3)
                            {
                                respuesta.nmEsquinaPosible3 = (String)row["nm_calle"];

                            }
                            else if (cont == 4)
                            {
                                respuesta.nmEsquinaPosible4 = (String)row["nm_calle"];

                            }
                            else if (cont == 5)
                            {
                                respuesta.nmEsquinaPosible5 = (String)row["nm_calle"];
                            }
                            cont++;
                        }
                    }
                    else if (dataSet != null && dataSet.Tables["posiblesCalles"] != null && dataSet.Tables["posiblesCalles"].Rows.Count > 0)
                    {
                        int cont = 1;
                        respuesta.posiblesCalles = true;
                        respuesta.tipoRequest = "mostrarPosiblesCalles";
                        respuesta.cantCalles = dataSet.Tables["posiblesCalles"].Rows.Count;
                        foreach (DataRow row in dataSet.Tables["posiblesCalles"].Rows)
                        {
                            if (cont == 1)
                            {
                                respuesta.nmCallePosible1 = (String)row["nm_calle"];
                            }
                            else if (cont == 2)
                            {
                                respuesta.nmCallePosible2 = (String)row["nm_calle"];

                            }
                            else if (cont == 3)
                            {
                                respuesta.nmCallePosible3 = (String)row["nm_calle"];

                            }
                            else if (cont == 4)
                            {
                                respuesta.nmCallePosible4 = (String)row["nm_calle"];

                            }
                            else if (cont == 5)
                            {
                                respuesta.nmCallePosible5 = (String)row["nm_calle"];
                            }
                            cont++;
                        }
                    }
                    else if (dataSet == null)
                    {
                        respuesta.tipoRequest = "mostrarPunto";
                        respuesta.encontre = false;
                    }
                    else
                    {
                        respuesta.tipoRequest = "mostrarPunto";
                        if (dataSet.Tables["interseccion"] != null)
                        {
                            respuesta.encontre = true;
                            foreach (DataRow row in dataSet.Tables["interseccion"].Rows)
                            {
                                respuesta.x = (double)row["punto_x"];
                                respuesta.y = (double)row["punto_y"];
                                if (tipo.Equals("origen"))
                                {
                                    respuesta.tipo = "origen";
                                }
                                else
                                {
                                    respuesta.tipo = "destino";
                                }
                                respuesta.nmCalle = (string)row["nm_calle"];
                                respuesta.nmEsquina = (string)row["nm_esquina"];
                            }
                        }
                        else
                        {
                            respuesta.encontre = false;
                        }
                    }
                }
                return this.Json(respuesta);
            }
            return this.Json(respuesta);
        }


        private int obtenerTiempoOmnibus(Pgmobile.calcularDemora.DatosDemora[] datoDemora, int idOmnibus)
        {
            bool encontre = false;
            int minutos = -1;
            for (int i = 0; i < datoDemora.Length && !encontre; i++)
            {
                if (datoDemora[i].IdOmnibus == idOmnibus)
                {
                    minutos = (int)Math.Floor(TimeSpan.FromMilliseconds(datoDemora[i].MiliSegundos).TotalMinutes);
                    encontre = true;
                }
            }
            return minutos;
        }


    }
}
